# encoding:utf-8
import json
import pickle
import traceback
import logging
from datetime import datetime
from io import BytesIO
import random

from flask import Blueprint, request, g, make_response
from flask_restful import Resource, Api, reqparse, marshal, fields, current_app

from common.utils.custom_output_json import custom_output_json
from common.utils.jwt_util import _generate_token, refresh_token
from common.models import rds, db, cache
from common.models.user import UserBase
from common.model_fields.user_fields import user_fields
from common.utils.utils import generate_code
from common.utils.login_util import check_code

user_bp = Blueprint('user_bp', __name__, url_prefix='/user')
api = Api(user_bp)


@api.representation('application/json')
def output_json(data, code=200, headers=None):
    return custom_output_json(data, code, headers)


class AuthorizationResource(Resource):
    """
    注册账号
    """

    def post(self):
        try:
            parser = reqparse.RequestParser()
            args_list = ['account', 'password', 'phone', 'code', 'uuid']
            for args in args_list:
                parser.add_argument(args, required=True)
            args = parser.parse_args()
            account = args.get('account')
            password = args.get('password')
            # 手机号
            phone = args.get('phone')
            # 图片验证码
            code = args.get('code')
            # 图片的uuid
            uuid = args.get('uuid')
            # # 短信验证码
            # msg_code = args.get('msg_code')

            if not all([account, password, phone, code]):
                return {'message': 'params is error', 'code': 400}

            # 图形验证码
            real_code = rds.get(uuid)
            if not real_code:
                return {'code': 407, 'message': '验证码过期'}
            real_code = real_code.decode()
            real_code = real_code.lower()
            code = code.lower()
            print('11111111', real_code, code)
            if real_code != code:
                return {'code': 406, 'message': '验证码错误'}

            # 注册账号时的短信验证
            # if not msg_code:
            #     return {'code': 406, 'message': '短信验证码错误'}
            # # 从redis中取出短信验证码
            # real_msg_code = rds.get(phone)
            # # 判断是否存在  不存在
            # if not real_msg_code:
            #     return {'code': 407, 'message': '短信验证码过期'}
            # real_msg_code = real_msg_code.decode()
            #
            # # 进行验证是否一致
            # if real_msg_code != msg_code:
            #     return {'code': 406, 'message': '短信验证码错误'}

            # 验证手机号是否已使用
            number = UserBase.query.filter_by(phone=phone).count()
            if number >= 1:
                return {'code': 405, 'result': '该手机已绑定用户，请更换手机号'}

            # 验证用户是否已经注册
            user = UserBase.query.filter_by(account=account).first()
            if user:
                return {'code': 405, 'result': '该用户已存在'}

            # 通过验证，注册用户
            user = UserBase(account=account, password=password, phone=phone)
            user.last_login = datetime.now()
            db.session.add(user)
            db.session.commit()
            return marshal(user, user_fields)
        except:
            error = traceback.format_exc()
            logging.error('register_user error:{}'.format(error))
            return {'error': error, 'code': 500}


class Login(Resource):
    """
    登录
    增加验证码验证
    """

    # @check_code
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('account')
        parser.add_argument('password')
        parser.add_argument('code')
        parser.add_argument('uuid')
        args = parser.parse_args()
        account = args.get('account')
        password = args.get('password')
        code = args.get('code')
        uuid = args.get('uuid')

        # 获取真正的图片验证码
        # real_code = rds.get(uuid)
        # if not real_code:
        #     return {'code': 407, 'message': '验证码过期'}
        # real_code = real_code.decode()
        # if real_code != code:
        #     return {'code': 406, 'message': '验证码错误'}
        # 判断用户账号密码是否正确
        user = UserBase.query.filter_by(account=account, password=password).first()
        if not user:
            return {'code': 406, 'result': '用户名或密码错误'}
        # 最后一次登录时间
        user.last_login = datetime.now()
        user_id = user.id
        db.session.commit()
        # 生成token
        token, refresh_token = _generate_token(account, user_id)
        return{'token': token, 'refresh_token': refresh_token, 'account': account,
                                          'uid': user_id}


class VerificationCode(Resource):
    """
    图片验证码
    """

    def get(self):
        try:
            parser = reqparse.RequestParser()
            parser.add_argument('uuid')
            args = parser.parse_args()
            uuid = args.get('uuid')

            # 生成图片验证码
            text, image = generate_code()
            # 保存验证码到redis
            rds.setex(uuid, 60 * 5, text)

            out = BytesIO()
            image.save(out, 'png')
            out.seek(0)
            resp = make_response(out.read())
            resp.content_type = 'image/png'
            return resp
        except:
            error = traceback.format_exc()
            logging.error('code image error{}'.format(error))
            return 'fail'


from celery_task.main import phone_code


class MessageCode(Resource):
    """
    短信验证码
    """

    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('phone')
        args = parser.parse_args()
        phone = args.get('phone')

        # 生成验证码
        code = str(random.randint(100000, 999999))
        # 发送验证码
        try:
            # 发送短信
            phone_code.delay(phone, code)
            # 把短信验证码存放到redis中
            rds.setex(phone, 60, code)
            return {'message': '发送验证码成功', 'code': 200}
        except:
            error = traceback.format_exc()
            logging.error('mes error:{}'.format(error))
            return {'message': error, 'code': 500}


class GetUserInfo(Resource):
    """
    获取用户基本信息
    """
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('uid')
        args = parser.parse_args()
        uid = args.get('uid')
        user = UserBase.query.get(uid)
        result = marshal(user, user_fields)
        result.update({'img': 'img.png'})
        return result


api.add_resource(AuthorizationResource, '/register_user', endpoint='user/register_user')
api.add_resource(Login, '/login', endpoint='/login')
api.add_resource(VerificationCode, '/code', endpoint='user/code')
api.add_resource(MessageCode, '/phone_code', endpoint='phone_code')
api.add_resource(GetUserInfo, '/get_user', endpoint='get_user')
